---
title: 'jenkins 实践'
date: '2024-11-10'
tags: ['jenkins']
draft: false
summary: "基于前端使用流水线等方式进行持续集成和持续交付。"
# images: ['/static/images/twitter-card.png']
---

#### 流水线

常见构建触发

- 快照依赖构建/Build whenever a SNAPSHOT dependency is built  
  当依赖的快照被构建时执行本 ob
- 触发远程构建（例如使用脚本）  
   远程调用本 job 的 restapi 时执行本 iob
- job 依赖构建/Build after other projects are built  
  当依赖的 job 被构建时执行本 job， 常见的是父子项目构建时使用，就是当前项目在父
  项目构建后触发
- 定时构建/Build periodically  
  Jenkins cron 表达式,使用 cron 表达式定时构建本 job  
  [标准 cron](https://crontab.guru)

  ```
  Jenkins cron不是标准的cron表达式
  第一个☆表示每个小时的第几分钟，取值0~59
  H☆☆☆☆
  H:每小时执行一次

  第二颗☆表示小时，取值0~23
  ☆15☆☆☆表示每天下午3点
  ☆1☆☆☆表示每天凌晨1点
  第三颗☆表示一个月的第几天，取值1~31
  ☆15☆☆表示每月5日凌晨1点
  第四颗☆表示第几月，取值1~12
  ☆1551☆表示每年几月执行
  第五颗☆表示一周中的第几天，取值0~7，其中0和7代表的都是周日
  ```

- 向 GitHubi 提交代码时触发 enkins 自动构建/GitHub hook trigger for GITScm
  polling  
  Github-VebHook 出发时构建本 job
- 定期检查代码变更/Poll SCM  
  使用 cron 表达式定时检查代码变更，变更后构建本 job

#### 配置构建节点

每台电脑的性能都是有限的，就像云服务主机一样出现并发访问，要做并发的构建就要构建
节点给负责构建的项目进行负载均衡。主要处理大项目或者项目多流程处理。
![构建节点](/static/images/jenkins/20250109160744.png) 1、负载的方式有多种 （可以结合项目构建）

- 轮询： 轮询节点构建项目。
- 主动：Jenkins 会在 SCM 上的变更被检测到时立即构建。
- 主动+轮询：Jenkins 会在 SCM 上的变更被检测到时立即构建，然后定期检查 SCM 上的
  变更。
- 标签：在项目构建时绑定节点标签，项目构建触发时在标签节点构建项目。

2、节点的配置 ![节点配置](/static/images/jenkins/20250109163519.png)

#### 流水线触发 Build Authorization Token Root

在构建流水线的时候需要自动和手动，手动直接点击就好了，自动触发需要远程仓库或
github 的 webhook 触发

- 首先在项目配置的构建触发器中添加构建令牌 ~[操作步骤](/static/images/jenkins/20250108223608.png)
- 在浏览器输入 `JENKINS_URL//job/cicd/build?token=TOKEN_NAME` 访问测试。
- 安装插件：Build Authorization Token Root 插件。主要作用是在 Jenkins 中使用令牌
  进行身份验证，以便允许或拒绝特定的用户或服务访问 Jenkins 实例。否则是直接跳到
  登录页或者是没有权限访问(例如切换浏览器输入路径)，无法触发构建。路径就变成
  了`JENKINS_URL/buildWithParameters?token=TOKEN_NAME`
- 在 Gitlab 中管理中配置网络服务，方便后面的 webhook 触发使用本地的网络 http 请
  求。 ![操作步骤](/static/images/jenkins/20250108220800.png)
- 到 Gitlab 项目设置中的 webhook 设置，输入
  `JENKINS_URL/buildWithParameters?token=TOKEN_NAME` 的触发 URL，勾选合并和推送
  事件，关掉 SSL 验证，在下方测试模拟请求，查看 Jenkins 构建触发，然后保存。
  ![操作步骤](/static/images/jenkins/20250108223906.png)

#### pipeline

pipeline 是 jenkins 的核心 属于脚步构建，通过项目上配置或者仓库配置触发，语法有
点类似 js ，[更多语法参考](https://www.jenkins.io/zh/doc/book/pipeline/)

```shell
完整语法
5个必备的组成部分
pipeline:整条流水线
agent:指定执行器 即构建的node
stages:所有阶段
stage:某一阶段，可有多个  项目配置选择为pipeline项目时可以查看多个流程
steps:阶段内的每一步，可执行命令

pipeline {
 agent any
 # 配置插件 没有插件下面没法安装代码
 tools {
  nodejs 'nodejs'
 }
 environment {
  NODE_VERSION = '18.16.0' 使用适当的 Node.js 版本
 }
 stages {
  stage('初始化') {
   steps {
   # 删除之前拉取的仓库文件夹
   "rm -rf ${git_dir}"
    echo 'Testing...'
    when {
     // 当分支为master时执行
     branch 'master'
    }
    # 当分支为master时执行
    exit()
    // 当分支不为master时执行 和上面when 效果一样,但是不并存在
    except {
     branch'!master'
    }
   }
  }
  stage('拉取代码') {
   steps {
    "git clone ${gitUrl}"
    echo 'Git...'
   }
  }
  stage('判断node版本') {
   steps {
    // 检查 nvm 是否已安装（在 Jenkins 代理上）
    def nvmInstalled = sh(script: 'command -v nvm &> /dev/null && echo true || echo false', returnStdout: true).trim() == 'true'

    if (!nvmInstalled) {
      error('nvm 未安装。请确保 Jenkins 代理上已安装 nvm。')
    }

    // 获取当前 Node.js 版本（如果已安装）
    def currentNodeVersion = sh(script: 'node -v 2>/dev/null || echo "not_installed"', returnStdout: true).trim()

    // 去除版本字符串中的 'v' 前缀（如果有）
    if (currentNodeVersion.startsWith('v')) {
      currentNodeVersion = currentNodeVersion.substring(1)
    }

    // 检查是否需要切换或安装版本
    if (currentNodeVersion != desiredNodeVersion && currentNodeVersion != 'not_installed') {
     // 尝试使用 nvm 切换版本
     sh "nvm use ${desiredNodeVersion}"

     // 再次检查版本以确保切换成功（有时 nvm use 不会立即生效）
     currentNodeVersion = sh(script: 'node -v', returnStdout: true).trim()
     if (currentNodeVersion.startsWith('v')) {
      currentNodeVersion = currentNodeVersion.substring(1)
     }

     if (currentNodeVersion != desiredNodeVersion) {
      // 切换失败，尝试安装新版本
      sh "nvm install ${desiredNodeVersion}"

      // 使用新安装的版本
      sh "nvm use ${desiredNodeVersion}"

      // 验证安装和切换是否成功
      currentNodeVersion = sh(script: 'node -v', returnStdout: true).trim()
      if (currentNodeVersion.startsWith('v')) {
       currentNodeVersion = currentNodeVersion.substring(1)
      }

      if (currentNodeVersion != desiredNodeVersion) {
       error("无法切换到或安装 Node.js 版本 ${desiredNodeVersion}。")
      }
     }
    } else if (currentNodeVersion == 'not_installed') {
     // Node.js 未安装，直接安装所需版本
     sh "nvm install ${desiredNodeVersion}"
     sh "nvm use ${desiredNodeVersion}"

     // 验证安装是否成功
     currentNodeVersion = sh(script: 'node -v', returnStdout: true).trim()
     if (currentNodeVersion.startsWith('v')) {
      currentNodeVersion = currentNodeVersion.substring(1)
     }

     if (currentNodeVersion != desiredNodeVersion) {
      error("无法安装 Node.js 版本 ${desiredNodeVersion}。")
     }
    }
    // 输出最终使用的 Node.js 版本
    echo "当前 Node.js 版本为 ${currentNodeVersion}。"
   }
  }
  stage('安装依赖') {
   steps {
   #三个双引号代表执行多个命令
    sh """
    npm install yarn -g
    yarn install
    """
    echo 'Git...'
   }
  }
  stage('测试分支') {
   steps {
    when {
     branch 'test'
    }
    # 执行测试 安装插件 Junit
    junit '**/target/*.xml'
    echo '测试代码'
   }
  }
  stage('Build') {
   steps {
    sh "yarn build"
    echo 'Building...'
   }
  }
  stage('Deploy') {
   steps {
    # 展示文件夹路径
    sh "pwd"
    echo 'Deploying...'
   }
  }
 }
}
```

#### blue ocean

流水执行的可视化界面, 可以查看流水线的执行情况, 可以查看流水线的执行历史, 但是下载的最新版本好像有些不兼容，好在正常功能可以使用。

![打开Blue Ocean](/static/images/jenkins/20250110121428.png)
![查看Blue Ocean，创建分支流水](/static/images/jenkins/20250110121619.png)

#### Publish Over SSH

- 先在插件安装 Publish Over SSH 插件
- 到管理 Jenkins -> 系统管理(System Configuration) -> Publish Over SSH -> 配置
  SSH Servers ![操作步骤](/static/images/jenkins/20250108210243.png)
- 到项目中，重新设置项目配置构建后操作 ![操作步骤](/static/images/jenkins/20250108211104.png)
- 重新启动查看打包是否完成，返回设置的路径啥的不合适，可以在打包完成后可以重新修
  改配置

- 打包次数多了，ssh 发送就会出错，所以要在打包构建前处理一些逻辑,解决同文件冲突
  问题 ![操作步骤](/static/images/jenkins/20250108213058.png)

#### 邮箱设置

邮箱分为发件邮箱和收件邮箱 ![发件邮箱](/static/images/jenkins/20250108233014.png)
![收件邮箱](/static/images/jenkins/20250108234142.png)

- 可以安装插件 Email Extension 支持个性化的邮件通知在系统设置显示的名称是
  Extended E-mail Notification
